#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

#define MAX_BUFFER_SIZE 10
#define NUM_PRODUCERS 2
#define NUM_CONSUMERS 5

typedef struct {
    int buffer[MAX_BUFFER_SIZE];
    int head, tail, count;
    pthread_mutex_t lock;
    pthread_cond_t not_empty, not_full;
} queue_t;

queue_t queue;

void init_queue(queue_t *q) {
    q->head = q->tail = q->count = 0;
    pthread_mutex_init(&(q->lock), NULL);
    pthread_cond_init(&(q->not_empty), NULL);
    pthread_cond_init(&(q->not_full), NULL);
}

void enqueue(queue_t *q, int item) {
    pthread_mutex_lock(&(q->lock));
    while (q->count == MAX_BUFFER_SIZE) {
        pthread_cond_wait(&(q->not_full), &(q->lock));
    }
    q->buffer[q->tail] = item;
    q->tail = (q->tail + 1) % MAX_BUFFER_SIZE;
    q->count++;
    pthread_cond_signal(&(q->not_empty)); // 通知消费者
    pthread_mutex_unlock(&(q->lock));
}

int dequeue(queue_t *q) {
    int item;
    pthread_mutex_lock(&(q->lock));
    while (q->count == 0) {
        pthread_cond_wait(&(q->not_empty), &(q->lock));
    }
    item = q->buffer[q->head];
    q->head = (q->head + 1) % MAX_BUFFER_SIZE;
    q->count--;
    pthread_cond_signal(&(q->not_full)); // 通知生产者
    pthread_mutex_unlock(&(q->lock));
    return item;
}

void *producer_func(void *arg) {
    int id = *((int *)arg);
    while (1) {
        int item = id * 100 + rand() % 100; // 示例数据
        printf("Producer %d produced item %d\n", id, item);
        enqueue(&queue, item);
        usleep(rand() % 1000000); // 模拟生产间隔
    }
    return NULL;
}

void *consumer_func(void *arg) {
    while (1) {
        int item = dequeue(&queue);
        printf("Consumer %lu consumed item %d\n", pthread_self(), item);
        usleep(rand() % 1000000); // 模拟消费间隔
    }
    return NULL;
}

int main() {
    srand(time(NULL));
    init_queue(&queue);
    pthread_t producers[NUM_PRODUCERS], consumers[NUM_CONSUMERS];
    int producer_ids[NUM_PRODUCERS] = {0, 1};
    // 创建生产者线程
    for (int i = 0; i < NUM_PRODUCERS; i++) {
        pthread_create(&producers[i], NULL, producer_func, &producer_ids[i]);
    }
    // 创建消费者线程
    for (int i = 0; i < NUM_CONSUMERS; i++) {
        pthread_create(&consumers[i], NULL, consumer_func, NULL);
    }
    // 等待所有线程完成（在实际应用中，这通常不会这样做，因为生产者和消费者是持续运行的）
    // 注意：这里不等待线程结束，因为示例中的生产者和消费者都是无限循环的
    // 实际应用中，你可能需要设计合适的退出机制
    printf("All threads created.\n");
    // sleep(30);
    int status = 0;
    pthread_join(producers[0], (void*)&status);
    return 0;
}